home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Sprite 1984 - 1993
/
Sprite 1984 - 1993.iso
/
src
/
kernel
/
mach
/
sun4.md
/
machMigrate.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-12-18
|
9KB
|
302 lines
/*
* machMigrate.c --
*
* Machine dependent code to support process migration. These routines
* encapsulate and deencapsulate the machine-dependent state of a
* process and set up the state of the process on its new machine.
*
* Copyright 1988 Regents of the University of California
* Permission to use, copy, modify, and distribute this
* software and its documentation for any purpose and without
* fee is hereby granted, provided that the above copyright
* notice appear in all copies. The University of California
* makes no representations about the suitability of this
* software for any purpose. It is provided "as is" without
* express or implied warranty.
*/
#ifndef lint
static char rcsid[] = "$Header: /cdrom/src/kernel/Cvsroot/kernel/mach/sun4.md/machMigrate.c,v 1.6 91/08/02 18:43:26 mgbaker Exp $ SPRITE (Berkeley)";
#endif /* not lint */
#include "sprite.h"
#include "machConst.h"
#include "machInt.h"
#include "mach.h"
#include "machMon.h"
#include "sched.h"
#include "procMigrate.h"
#include <stdio.h>
#include <bstring.h>
/*
* The information that is transferred between two machines.
*/
typedef struct MigratedState {
Mach_RegState trapRegs; /* The pointer to trapRegs in state
* should be set to point to this in the
* deencap routine. It usually
* points to the kernel stack, but
* this won't exist yet on a
* migrated process. */
int fpuStatus; /* See Mach_State. */
int lastSysCall; /* Used in sys module. */
int savedArgI0; /* Arg 0 saved for sys call. */
} MigratedState;
/*
* ----------------------------------------------------------------------------
*
* Mach_EncapState --
*
* Copy the machine-dependent information for a process into
* a buffer. The buffer passed to the routine must contain space for
* a MigratedState structure, the size of which is accessible via
* another procedure.
*
* Results:
* SUCCESS.
* The buffer is filled with the user state and PC of the process.
*
* Side effects:
* None.
*
* ----------------------------------------------------------------------------
*/
/* ARGSUSED */
ReturnStatus
Mach_EncapState(procPtr, hostID, infoPtr, buffer)
register Proc_ControlBlock *procPtr; /* The process being migrated */
int hostID; /* host to which it migrates */
Proc_EncapInfo *infoPtr; /* area w/ information about
* encapsulated state */
Address buffer; /* Pointer to allocated buffer */
{
Mach_State *machStatePtr = procPtr->machStatePtr;
MigratedState *migPtr = (MigratedState *) buffer;
if (machStatePtr->fpuStatus & MACH_FPU_ACTIVE) {
if (proc_MigDebugLevel > 2) {
printf("Mach_EncapState: FPU was active (fsr %x), dumping state.\n",
procPtr->machStatePtr->fpuStatus);
}
/*
* We may or may not have saved the floating point state from the
* FPU. If an exception is pending then we must of done a
* save and doing another will overwrite the exception.
*/
if ((machStatePtr->fpuStatus & MACH_FPU_EXCEPTION_PENDING) == 0) {
MachFPUDumpState(machStatePtr->trapRegs);
if (machStatePtr->fpuStatus & MACH_FPU_EXCEPTION_PENDING) {
machStatePtr->fpuStatus |=
(machStatePtr->trapRegs->fsr & MACH_FSR_TRAP_TYPE_MASK);
}
}
if (proc_MigDebugLevel > 2) {
printf("Mach_EncapState: FPU fsr now %x.\n",
procPtr->machStatePtr->fpuStatus);
}
}
/*
* There must not be any saved window state for migration. This shouldn't
* ever happen the way things are set up.
*/
if (machStatePtr->savedMask != 0) {
panic("Mach_EncapState: saved window state of proc isn't empty.\n");
}
bcopy((Address) machStatePtr->trapRegs, (Address) &migPtr->trapRegs,
sizeof (Mach_RegState));
/* Copy necessary fields from state structure. */
migPtr->fpuStatus = machStatePtr->fpuStatus;
migPtr->lastSysCall = machStatePtr->lastSysCall;
migPtr->savedArgI0 = machStatePtr->savedArgI0;
return(SUCCESS);
}
/*
* ----------------------------------------------------------------------------
*
* Mach_DeencapState --
*
* Copy the machine-dependent information for a process from
* a buffer. The buffer passed to the routine must contain
* a MigratedState structure created by Mach_EncapState on the
* machine starting a migration.
*
* Results:
* The user state and PC of the process are initialized from the
* encapsulated information, and the other standard process
* initialization operations are performed (by the general initialization
* procedure). The status from that procedure is returned.
*
* Side effects:
* None.
*
* ----------------------------------------------------------------------------
*/
/* ARGSUSED */
ReturnStatus
Mach_DeencapState(procPtr, infoPtr, buffer)
register Proc_ControlBlock *procPtr; /* The process being migrated */
Proc_EncapInfo *infoPtr; /* information about the buffer */
Address buffer; /* buffer containing data */
{
MigratedState *migPtr = (MigratedState *) buffer;
Mach_State state;
ReturnStatus status;
if (infoPtr->size != sizeof(MigratedState)) {
if (proc_MigDebugLevel > 0) {
printf("Mach_DeencapState: warning: host %d tried to migrate",
procPtr->peerHostID);
printf(" onto this host with wrong structure size.");
printf(" Ours is %d, theirs is %d.\n",
sizeof(MigratedState), infoPtr->size);
}
return(PROC_MIGRATION_REFUSED);
}
/*
* Get rid of the process's old machine-dependent state if it exists.
*/
if (procPtr->machStatePtr != (Mach_State *) NIL) {
Mach_FreeState(procPtr);
}
bzero((char *) &state, sizeof (Mach_State));
state.switchRegs = (Mach_RegState *) NIL;
/*
* Set trapRegs to the trapRegs area of the migrated state.
*/
state.trapRegs = &migPtr->trapRegs;
/* Get other necessary fields for Mach_State structure. */
state.fpuStatus = migPtr->fpuStatus;
state.lastSysCall = migPtr->lastSysCall;
state.savedArgI0 = migPtr->savedArgI0;
/* Don't pass the pc explicitly -- it will be gotten from trapRegs. */
status = Mach_SetupNewState(procPtr, &state,
Proc_ResumeMigProc, (Address)NIL, TRUE);
/*
* Mach_SetupNewState thinks that all new processes have a clean FPU
* slate, and it zeroes the mach state. Make sure to keep any
* pending exceptions.
*/
if (proc_MigDebugLevel > 2) {
printf("Mach_DeencapState: FPU status register was %x.\n",
migPtr->fpuStatus);
}
if (migPtr->fpuStatus) {
procPtr->machStatePtr->fpuStatus = migPtr->fpuStatus;
procPtr->specialHandling = 1;
}
return(status);
}
/*
* ----------------------------------------------------------------------------
*
* Mach_GetEncapSize --
*
* Return the size of the encapsulated machine-dependent data.
*
* Results:
* SUCCESS is returned directly; the size of the encapsulated state
* is returned in infoPtr->size.
*
* Side effects:
* None.
*
* ----------------------------------------------------------------------------
*
*/
/* ARGSUSED */
ReturnStatus
Mach_GetEncapSize(procPtr, hostID, infoPtr)
Proc_ControlBlock *procPtr; /* process being migrated */
int hostID; /* host to which it migrates */
Proc_EncapInfo *infoPtr; /* area w/ information about
* encapsulated state */
{
infoPtr->size = sizeof(MigratedState);
return(SUCCESS);
}
/*
* ----------------------------------------------------------------------------
*
* Mach_CanMigrate --
*
* Indicate whether a process's trapstack is in a form suitable for
* starting a migration. We require that nextPc follow pc -- if
* we just did a jump, then we defer migration momentarily.
*
* Results:
* TRUE if we can migrate using this trapstack, FALSE otherwise.
*
* Side effects:
* None.
*
* ----------------------------------------------------------------------------
*/
Boolean
Mach_CanMigrate(procPtr)
Proc_ControlBlock *procPtr; /* pointer to process to check */
{
Boolean okay;
Mach_RegState *regsPtr;
okay = TRUE;
regsPtr = procPtr->machStatePtr->trapRegs;
if (regsPtr->nextPc != regsPtr->pc + 4) {
okay = FALSE;
}
if (proc_MigDebugLevel > 4) {
printf("Mach_CanMigrate called. PC %x, returning %d.\n",
regsPtr->pc, okay);
}
return okay;
}
/*
*----------------------------------------------------------------------
*
* Mach_GetLastSyscall --
*
* Return the number of the last system call performed for the current
* process.
*
* Results:
* The system call number is returned.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
int
Mach_GetLastSyscall()
{
Proc_ControlBlock *procPtr; /* pointer to process to check */
procPtr = Proc_GetCurrentProc();
return(procPtr->machStatePtr->lastSysCall);
}